<template>
  <div class="websiteTree">
    <el-row v-if="showFilter" style="width: 100%">
      <el-col :span="24">
        <el-input
          v-model="filterText"
          :placeholder="$t('输入关键字进行过滤')"
          clearable
          @input="searchEvent()"
        />
      </el-col>
      <el-col v-if="operation.showTreeBtn" :span="6">
        <slot name="tree-add-button" />
      </el-col>
    </el-row>
    <el-scrollbar :style="{ height: height || treeHeight }">
      <vxe-table
        ref="websiteTree"
        size="small"
        border="none"
        show-overflow
        :row-config="{ isCurrent: true, keyField: rowId }"
        :show-header="false"
        :data="filterTreeData"
        :radio-config="{
          labelField: 'label',
          checkRowKey,
          checkMethod: checkMethod,
        }"
        :checkbox-config="{
          labelField: 'label',
          reserve: true,
          checkRowKeys,
          checkStrictly: checkStrictly,
          checkMethod: checkMethod,
        }"
        :cell-style="{ height: '35px' }"
        :loading="loading || cusLoading"
        :tree-config="{
          line: true,
          expandAll: expandAll,
        }"
        @current-change="currentChange"
        @radio-change="radioChange"
        @checkbox-change="checkboxChange"
        @checkbox-all="checkboxAll"
      >
        <vxe-column v-if="treeSelectType === 'radio'" type="radio" tree-node>
          <template #radio="{ row, checked }">
            <div
              class="tree-label"
              :class="{ 'is-disabled': disabledChecked(row) }"
              @click="handleLabelClick(row)"
            >
              <Folder v-if="!checked" class="radio-select-icon" />
              <FolderChecked v-else class="radio-select-icon" />
               <span
                  v-html="row.label"
                  style="
                    overflow: hidden;
                    flex: 1;
                    text-overflow: ellipsis;
                    white-space: nowrap;
                  "
                />
            </div>
          </template>
        </vxe-column>
        <vxe-column
          v-if="treeSelectType === 'checkbox'"
          type="checkbox"
          tree-node
        >
          <template #default="{ row }">
            <span v-html="row.label" />
          </template>
        </vxe-column>
        <vxe-column
          v-if="operation.data"
          :title="$t('操作')"
          :width="operation.width + 'px'"
        >
          <template #default="{ row }">
            <vxe-button
              v-for="item in operation.data"
              :key="item.title"
              style="margin-left: 3px"
              type="text"
              :icon="item.icon"
              :title="item.title"
              @click="handleClick(item, row)"
            />
          </template>
        </vxe-column>
      </vxe-table>
    </el-scrollbar>
    <div v-if="treeSelectBtn">
      <el-button type="default" @click="emitCloseEvent">
        {{ cancelText || $t("取消") }}
      </el-button>
      <el-button :type="saveType || 'primary'" @click="onSubmit">
        {{ saveText || $t("保存") }}
      </el-button>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, watch, onMounted, nextTick } from "vue";
import { setContentHeight } from "@/utils/mUtils";
import * as api from "@/api/index.js";
import XEUtils from "xe-utils";
import i18n from "@/lang/index.js";
// 定义props
const props = defineProps({
  // 组件高度
  height: {
    type: String,
    default: "",
  },
  // 操作按钮
  operation: {
    type: Object,
    default: () => ({}),
  },
  // 自定义树结构数据
  treeCusData: {
    type: Array,
    default: () => null,
  },
  // 自定义加载状态
  cusLoading: {
    type: Boolean,
    default: false,
  },
  // 树形结构区分单选还是多选
  treeSelectType: {
    type: String,
    default: "radio",
  },
  // 选中的数据
  checkedRowKeys: {
    type: Array,
    default: () => [],
  },
  checkRowKey: {
    type: String,
    default: "",
  },
  // 行id
  rowId: {
    type: String,
    default: "id",
  },
  // 是否显示筛选框
  showFilter: {
    type: Boolean,
    default: true,
  },
  // 自定义元素的高度
  cusHeight: {
    type: Number,
    default: 0,
  },
  // 筛选参数
  filterValue: {
    type: String,
    default: "",
  },
  // 是否展开全部
  expandAll: {
    type: Boolean,
    default: true,
  },
  // 父子不关联
  checkStrictly: {
    type: Boolean,
    default: false,
  },
  // 禁用函数
  checkMethod: {
    type: Function,
    default: () => true,
  },
  disabledCheckKeys: {
    type: Array,
    default: () => [],
  },
  saveType: {
    type: String,
    default: "",
  },
  cancelText: {
    type: String,
    default: "取消",
  },
  saveText: {
    type: String,
    default: "保存",
  },
  treeSelectBtn: {
    type: Boolean,
    default: false,
  },
});

// 定义emits
const emit = defineEmits([
  "handleNodeClick",
  "handleCheckboxChange",
  "handleLabelClick",
  "cancel",
  "handleSelectionChange",
  "getWebsiteData"
]);

// 响应式数据
const websiteTree = ref(null);
const treeData = ref([]);
const loading = ref(false);
const filterText = ref("");
const filterTreeData = ref([]);
const treeHeight = ref("");
const checkRowKeys = ref(props.checkedRowKeys);
const multipleSelection = ref([]);
// 监听props变化
watch(
  () => props.treeCusData,
  (val) => {
    if (!val) return;
    treeData.value = val;
    searchEvent();
  }
);

watch(
  () => props.filterValue,
  (val) => {
    searchEvent(val);
  }
);

// 生命周期钩子
onMounted(() => {
  nextTick(() => {
    treeHeight.value = computTreeHeight();
  });
  if (!props.treeCusData) {
    getWebsiteData();
  }
});

// 方法
// 获取网点数据
const getWebsiteData = async () => {
  loading.value = true;
  try {
    const res = await api.default.system.organization.list();
    treeData.value = formatterLabel(res.data);
    searchEvent();
    loading.value = false;
  } catch {
    loading.value = false;
  }
};

// 格式化树
const formatterLabel = (data) => {
  if (data && data.length > 0) {
    data.forEach((it) => {
      it.name = i18n.global.t(it.label);
      it.label = `${i18n.global.t(it.label)} (${it.code})`;
      if (it.children) {
        formatterLabel(it.children);
      }
    });
  }
  return data;
};

const searchEvent = (val) => {
  const filterTextValue = val || filterText.value;
  const filterName = XEUtils.toValueString(filterTextValue)
    .trim()
    .toLowerCase();
  if (filterName) {
    const filterRE = new RegExp(filterName, "gi");
    const options = { children: "children" };
    const searchProps = ["label"];
    const rest = XEUtils.searchTree(
      treeData.value,
      (item) =>
        searchProps.some(
          (key) =>
            XEUtils.toValueString(item[key]).toLowerCase().indexOf(filterName) >
            -1
        ),
      options
    );
    XEUtils.eachTree(
      rest,
      (item) => {
        searchProps.forEach((key) => {
          item[key] = XEUtils.toValueString(item[key]).replace(
            filterRE,
            (match) => `<span class="keyword-lighten">${match}</span>`
          );
        });
      },
      options
    );
    filterTreeData.value = rest;
  } else {
    filterTreeData.value = treeData.value;
  }
  // 搜索之后默认展开所有子节点
  setAllTreeExpand(true);
};

const currentChange = ({ row }) => {
  if (props.treeSelectType === "radio" && !disabledChecked(row)) {
    websiteTree.value.setRadioRow(row);
    emit("handleNodeClick", row);
  }
};

const radioChange = ({ row }) => {
  websiteTree.value.setCurrentRow(row);
  emit("handleNodeClick", row);
};

const checkboxChange = ({ row }) => {
  const list = [
    ...websiteTree.value.getCheckboxReserveRecords(),
    ...websiteTree.value.getCheckboxRecords(),
  ];
  multipleSelection.value = list;
  emit("handleCheckboxChange", row);
};

const onSubmit = () => {
  emit("handleSelectionChange", multipleSelection.value);
};

const getCheckboxRecords = () => {
  return websiteTree.value.getCheckboxRecords();
};

const setCheckboxRow = (rows, checked) => {
  websiteTree.value.setCheckboxRow(rows, checked);
};

const computTreeHeight = () => {
  return setContentHeight(38 + props.cusHeight);
};

const setAllTreeExpand = (checked) => {
  nextTick(() => {
    websiteTree.value.setAllTreeExpand(checked);
  });
};

const handleLabelClick = (row) => {
  if (!disabledChecked(row)) {
    emit("handleLabelClick", row);
  }
};

const handleClick = (item, row) => {
  if (item.handleClick) {
    item.handleClick(row);
  }
};

const checkboxAll = ({ checked }) => {
  const list = [
    ...websiteTree.value.getCheckboxReserveRecords(),
    ...websiteTree.value.getCheckboxRecords(),
  ];
  multipleSelection.value = list;
  emit("handleSelectionChange", list);
};

const disabledChecked = (row) => {
  return (
    props.disabledCheckKeys &&
    props.disabledCheckKeys.includes(row[props.rowId])
  );
};

const emitCloseEvent = () => {
  emit("cancel");
};

// 暴露方法给父组件
defineExpose({
  getCheckboxRecords,
  setCheckboxRow,
  setAllTreeExpand,
  searchEvent,
  getWebsiteData
});
</script>

<style lang="scss" scoped>
.websiteTree {
  padding: 5px;
  background-color: #fff;
  :deep() .keyword-lighten {
    color: #000;
    background-color: #ffff00;
  }
  .radio-select-icon {
    width: 17px;
    height: 17px;
    margin-right: 5px;
  }
  :deep() .vxe-button.type--text {
    padding-bottom: 3px;
    padding-top: 3px;
  }
  .tree-label {
    cursor: pointer;
    display: flex;
    align-items: center;
    &.is-disabled {
      cursor: default;
      color: #a2a5a7;
    }
  }
}
</style>
